package com.xyht.medicine_management_system.modules.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xyht.medicine_management_system.auth.entity.PermissionEntity;
import com.xyht.medicine_management_system.auth.util.JwtTokenUtil;
import com.xyht.medicine_management_system.common.commonReturn.CommonCodeEnum;
import com.xyht.medicine_management_system.common.commonReturn.CommonResult;
import com.xyht.medicine_management_system.common.commonReturn.ResponseResult;
import com.xyht.medicine_management_system.common.util.CacheUtil;
import com.xyht.medicine_management_system.modules.user.entity.MmsApplication;
import com.xyht.medicine_management_system.modules.user.entity.MmsRole;
import com.xyht.medicine_management_system.modules.user.entity.MmsRoleApplicationRelation;
import com.xyht.medicine_management_system.modules.user.entity.req.AuthReq;
import com.xyht.medicine_management_system.modules.user.entity.resp.AuthResp;
import com.xyht.medicine_management_system.modules.user.entity.resp.MmsApplicationResp;
import com.xyht.medicine_management_system.modules.user.mapper.MmsApplicationMapper;
import com.xyht.medicine_management_system.modules.user.mapper.MmsRoleApplicationRelationMapper;
import com.xyht.medicine_management_system.modules.user.mapper.MmsRoleMapper;
import com.xyht.medicine_management_system.modules.user.service.AuthorizationService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static com.xyht.medicine_management_system.auth.constant.CommonConstant.CLIENT_HEADER;
import static com.xyht.medicine_management_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.medicine_management_system.modules.user.constant.OpenCloseStatusConstant.OPEN_CLOSE_STATUS_OPEN;
import static com.xyht.medicine_management_system.modules.user.constant.UpDownConstant.APP_UP;

@Service
public class AuthorizationServiceImpl implements AuthorizationService {
    @Resource
    private CacheUtil cacheUtil;
    @Resource
    private MmsRoleApplicationRelationMapper mmsRoleApplicationRelationMapper;
    @Resource
    private MmsApplicationMapper mmsApplicationMapper;
    @Resource
    private JwtTokenUtil jwtTokenUtil;
    @Resource
    private MmsRoleMapper mmsRoleMapper;

    @Override
    public ResponseResult userUseGetAppList(String user_id) {
        List<MmsApplicationResp> respList = new ArrayList<>();

        List<String> roleList = cacheUtil.getRoleList(user_id);
        if (roleList == null || roleList.size() < 1) {
            return CommonResult.success(respList);
        }

        List<String> appIDList = mmsRoleApplicationRelationMapper.selectList(new LambdaQueryWrapper<MmsRoleApplicationRelation>()
                        .in(MmsRoleApplicationRelation::getRoleId, roleList))
                .stream()
                .map(MmsRoleApplicationRelation::getAppId)
                .distinct()
                .collect(Collectors.toList());
        if (appIDList.size() < 1) {
            return CommonResult.success(respList);
        }

        respList = mmsApplicationMapper.selectList(new LambdaQueryWrapper<MmsApplication>()
                        .in(MmsApplication::getId, appIDList)
                        .eq(MmsApplication::getUpDown, APP_UP))
                .stream()
                .map(application -> {
                    MmsApplicationResp applicationResp = new MmsApplicationResp();
                    BeanUtils.copyProperties(application, applicationResp);
                    return applicationResp;
                })
                .collect(Collectors.toList());
        return CommonResult.success(respList);
    }

    @Override
    public ResponseResult isAppPermission(String requestPath, HttpServletRequest request) {
        if (isNullOrEmpty(requestPath)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        PermissionEntity permissionEntity = new PermissionEntity();
        String user_id = jwtTokenUtil.getUserIdByRequest(request);

        List<String> roleList = cacheUtil.getRoleList(user_id);
        if (roleList.size() < 1) {
            permissionEntity.setIsPermission(false);
            return CommonResult.success(permissionEntity);
        }

        List<MmsRoleApplicationRelation> roleApplicationRelationList = mmsRoleApplicationRelationMapper.selectList(
                new QueryWrapper<MmsRoleApplicationRelation>()
                        .lambda().select(MmsRoleApplicationRelation::getAppId)
                        .in(MmsRoleApplicationRelation::getRoleId, roleList)
                        .groupBy(MmsRoleApplicationRelation::getAppId));
        List<String> appList = roleApplicationRelationList.stream().map(MmsRoleApplicationRelation::getAppId).collect(Collectors.toList());
        if (appList.size() < 1) {
            permissionEntity.setIsPermission(false);
            return CommonResult.success(permissionEntity);
        }
        permissionEntity.setIsPermission(true);
        return CommonResult.success(permissionEntity);
    }

    @Override
    public ResponseResult getAuthList(String roleId) {
        MmsRole smsRole = mmsRoleMapper.selectById(roleId);
        if (smsRole == null) {
            return CommonResult.failed(CommonCodeEnum.ROLE_NOT_EXIST);
        }

        //查询所有界面应用
        List<MmsApplication> appList = mmsApplicationMapper.selectList(new QueryWrapper<>());
        List<MmsRoleApplicationRelation> openAppList = mmsRoleApplicationRelationMapper.selectList(new QueryWrapper<MmsRoleApplicationRelation>()
                .lambda()
                .eq(MmsRoleApplicationRelation::getRoleId, roleId));
        List<String> openAppIDList = openAppList.stream().map(MmsRoleApplicationRelation::getAppId).collect(Collectors.toList());

        List<AuthResp> appRespList = appList.stream().map(smsApplication -> {
            AuthResp authResp = new AuthResp();
            BeanUtils.copyProperties(smsApplication, authResp);
            if (openAppIDList.stream().filter(id -> id.equals(smsApplication.getId().toString())).count() == 1) {
                authResp.setIsOpen(OPEN_CLOSE_STATUS_OPEN);
            }
            return authResp;
        }).collect(Collectors.toList());
        return CommonResult.success(appRespList);
    }

    @Override
    public ResponseResult updateApplication(AuthReq authReq) {
        if (isNullOrEmpty(authReq.getAppId(), authReq.getRoleId(), authReq.getStatus())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        MmsApplication smsApplication = mmsApplicationMapper.selectById(authReq.getAppId());
        if (smsApplication == null) {
            return CommonResult.failed(CommonCodeEnum.AUTH_APP_NOT_EXIST);
        }
        MmsRole smsRole = mmsRoleMapper.selectById(authReq.getRoleId());
        if (smsRole == null) {
            return CommonResult.failed(CommonCodeEnum.ROLE_NOT_EXIST);
        }

        //开启界面 导入关系
        if (authReq.getStatus() == OPEN_CLOSE_STATUS_OPEN) {
            List<MmsRoleApplicationRelation> list = mmsRoleApplicationRelationMapper.selectList(new LambdaQueryWrapper<MmsRoleApplicationRelation>()
                    .eq(MmsRoleApplicationRelation::getAppId, authReq.getAppId())
                    .eq(MmsRoleApplicationRelation::getRoleId, authReq.getRoleId()));
            if (list == null || list.size() < 1) {
                MmsRoleApplicationRelation applicationRelation = new MmsRoleApplicationRelation();
                BeanUtils.copyProperties(authReq, applicationRelation);
                mmsRoleApplicationRelationMapper.insert(applicationRelation);
            }
        } else {
            //关闭界面 删除关系
            QueryWrapper<MmsRoleApplicationRelation> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(MmsRoleApplicationRelation::getAppId, authReq.getAppId())
                    .eq(MmsRoleApplicationRelation::getRoleId, authReq.getRoleId());

            mmsRoleApplicationRelationMapper.delete(queryWrapper);
        }
        return CommonResult.success();
    }
}
